cmake_minimum_required(VERSION 2.6)
project(UGame)

# 编译选项 ########################################################################
option(HAS_MAIN_CC "Build-in main function")
option(BUILD_NET "Build Net module")
option(BUILD_NET_CLIENT "Build Net-Client module")
option(BUILD_DATA "Build Data module")
option(BUILD_CRYPTO "Build Crypto module")

if (UNIX)
    add_definitions(-Wall)
    if (CMAKE_COMPILER_IS_GNUCXX)
        add_definitions(-std=gnu++0x)
    else ()
        add_definitions(-std=stdc++11)
    endif()
endif()
add_definitions(-D_BUILD)

# 配置工程 ########################################################################
set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
include(cmake/CheckSystemPlatform.cmake)
CHECK_SYSTEM_PLATFORM(SYSTEM_PLATFORM SYSTEM_ARCH SYSTEM_ENDIAN)
configure_file(config.h.in ${PROJECT_SOURCE_DIR}/config.h)

# 独立编译需要外部库的代码需要指定外部库位置 ######################################
if (BUILD_NET)
    # LIBEVENT
    if(NOT LIBEVENT_FOUND)
        set(LIBEVENT_INCLUDE_DIR "" CACHE PATH "LIBEVENT INCLUDE DIR")
        include_directories( ${LIBEVENT_INCLUDE_DIR} )
    endif()
endif()
if (BUILD_DATA)
    # MYSQL
    if (NOT MYSQL_FOUND)
        set(MYSQL_INCLUDE_DIR "" CACHE PATH "MYSQL INCLUDE DIR")
        include_directories( ${MYSQL_INCLUDE_DIR} )
    endif()
endif()
if (BUILD_DATA OR BUILD_NET)
    # BOOST
    if (NOT BOOST_FOUND)
        set(BOOST_INCLUDE_DIR "" CACHE PATH "BOOST INCLUDE DIR")
        include_directories( ${BOOST_INCLUDE_DIR} )
    endif()
endif()
if (BUILD_CRYPTO)
    # OPENSSL
    if (NOT OPENSSL_FOUND)
        set(OPENSSL_INCLUDE_DIR "" CACHE PATH "OPENSSL INCLUDE DIR")
        include_directories( ${OPENSSL_INCLUDE_DIR} )
    endif()
endif()
# TINYXML
if (NOT TINYXML_FOUND)
    set(TINYXML_INCLUDE_DIR "" CACHE PATH "TINYXML INCLUDE DIR")
    include_directories( ${TINYXML_INCLUDE_DIR} )
endif()
# 工程包含目录 ####################################################################
include_directories(
    ${PROJECT_SOURCE_DIR}/..
)

# Base ############################################################################
set(UGame_SRC
    ${PROJECT_SOURCE_DIR}/config.h
    
    Platform.h
    Macros.h
    AtExit.h
    AtExit.cc
    Singleton.h
    Exception.h
    Exception.cc
    ErrorHandler.h
    
    Base/AtomicValue.h
    Base/Console.h
)
# Binary ########################################################################
set(UGame_Binary_SRC
    Binary/ByteBuffer.h
    Binary/ByteBuffer.cc
    Binary/ByteConverter.h
)
# Policies ########################################################################
set(UGame_Policies_SRC
    Policies/CreatePolicy.h
    Policies/LifeTimePolicy.h
    Policies/ThreadingModel.h
)
# System ##########################################################################
set(UGame_System_SRC
    System/LockGuard.h
    System/Mutex.h
    System/Mutex.cc
    System/Event.h
    System/Event.cc
    System/Runnable.h
    System/Thread.h
    System/Thread.cc
    System/Error.h
    System/Error.cc
)
# Util ############################################################################
set(UGame_Util_SRC
    Util/Option.h
    Util/Option.cc
    Util/OptionSet.h
    Util/OptionSet.cc
    Util/Application.h
    Util/Application.cc
    Util/String.h
    Util/String.cc
    Util/Path.h
    Util/Path.cc
    Util/Time.h
    Util/SubSystem.h
    Util/ByteConverter.h
    Util/LockedQueue.h
    Util/Configuration.h
    Util/XmlConfiguration.h
    Util/XmlConfiguration.cc
)
# Net #############################################################################
if (BUILD_NET)
    set(UGame_Net_SRC
        Net/SocketApi.h
        Net/TcpConnection.h
        Net/TcpConnectionFactory.h
        Net/TcpListener.h
        Net/TcpListener.cc
        Net/TcpRunnable.h
        Net/TcpRunnable.cc
        Net/TcpServer.h
        Net/TcpServer.cc
        Net/TcpSocket.h
        Net/TcpSocket.cc
    )
endif()
if (BUILD_NET_CLIENT)
    set(UGame_NetClient_SRC
        Net/TcpClient.h
        Net/TcpClient.cc
        Net/TcpDispatcher.h
        Net/TcpDispatcher.cc
        Net/TcpClientDelegate.h
        Net/TcpDispatcherCluster.h
        Net/TcpDispatcherCluster.cc
    )
endif()
# Data ############################################################################
if (BUILD_DATA)
    set(UGame_Data_SRC
        Data/Rel/Field.h
        Data/Rel/Field.cc
        Data/Rel/QueryResult.h
        Data/Rel/QueryResult.cc
        Data/Rel/SqlPreparedStatement.h
        Data/Rel/SqlPreparedStatement.cc
        Data/Rel/SqlConnection.h
        Data/Rel/SqlConnection.cc
        Data/Rel/SqlConnectionFactory.h
        Data/Rel/SqlConnectionFactory.cc
        Data/Rel/SqlConnectionFactoryImpl.h
        Data/Rel/Session.h
        Data/Rel/Session.cc
        Data/Rel/SqlDelayThread.h
        Data/Rel/SqlDelayThread.cc
        Data/Rel/SqlOperation.h
        Data/Rel/SqlOperation.cc
        Data/Rel/Callbacks.h
        Data/Rel/SessionImpl.h
    
        Data/Rel/Details/MySQLConnection.h
        Data/Rel/Details/MySQLConnection.cc
        Data/Rel/Details/MySQLConnectionFactoryImpl.h
        Data/Rel/Details/MySQLConnectionFactoryImpl.cc
        Data/Rel/Details/MySQLQueryResult.h
        Data/Rel/Details/MySQLQueryResult.cc
        Data/Rel/Details/MySQLConnector.h
        Data/Rel/Details/MySQLConnector.cc
    )
endif()

if (BUILD_CRYPTO)
    set(UGame_Crypto_SRC
        Crypto/BigNumber.h
        Crypto/BigNumber.cc
        Crypto/Hmac.h
        Crypto/Hmac.cc
        Crypto/Sha1.h
        Crypto/Sha1.cc
        
        Auth/SRP6.h
        Auth/SRP6.cc
    )
endif()

# Main.cc #########################################################################
if (HAS_MAIN_CC)
    set(UGame_SRC
        Main.cc
    ${UGame_SRC})
endif()

# 平台相关代码文件 ################################################################
if(WIN32)
    set(UGame_SRC
        Base/Console_WIN32.h
        Base/Console_WIN32.cc
    ${UGame_SRC})
    
    set(UGame_System_SRC
        System/Mutex_WIN32.h
        System/Mutex_WIN32.cc
        System/Event_WIN32.h
        System/Event_WIN32.cc
        System/Thread_WIN32.h
        System/Thread_WIN32.cc
        System/Error_WIN32.cc
    ${UGame_System_SRC})
    
    set(UGame_Util_SRC
        Util/String_WIN32.cc
        Util/Time_WIN32.cc
    ${UGame_Util_SRC})
    
    if (BUILD_NET)
        set(UGame_Net_SRC
            Net/SocketApi_WIN32.cc
            Net/TcpListener_WIN32.cc
            Net/TcpSocket_WIN32.cc
        ${UGame_Net_SRC})
    endif()
    
    if (BUILD_DATA)
        set(UGame_Data_SRC
            Data/Rel/Field_WIN32.cc
            Data/Rel/Details/MySQLConnection_WIN32.cc
        ${UGame_Data_SRC})
    endif()
elseif(UNIX)
    set(UGame_SRC
        Base/Console_POSIX.h
        Base/Console_POSIX.cc
    ${UGame_SRC})

    set(UGame_System_SRC
        System/Mutex_POSIX.h
        System/Mutex_POSIX.cc
        System/Event_POSIX.h
        System/Event_POSIX.cc
        System/Thread_POSIX.h
        System/Thread_POSIX.cc
        System/Error_POSIX.cc
    ${UGame_System_SRC})
    
    set(UGame_Util_SRC
        Util/String_POSIX.cc
        Util/Time_POSIX.cc
    ${UGame_Util_SRC})
    
    if (BUILD_NET)
        set(UGame_Net_SRC
            Net/SocketApi_POSIX.cc
            Net/TcpListener_POSIX.cc
            Net/TcpSocket_POSIX.cc
        ${UGame_Net_SRC})
    endif()
    
    if (BUILD_DATA)
        set(UGame_Data_SRC
            Data/Rel/Field_POSIX.cc
            Data/Rel/Details/MySQLConnection_POSIX.cc
        ${UGame_Data_SRC})
    endif()
endif()

# 构建库 ##########################################################################
set(UGame_BUILD_SRC
    ${UGame_SRC}
    ${UGame_Policies_SRC}
    ${UGame_System_SRC}
    ${UGame_Util_SRC}
    ${UGame_Binary_SRC}
)
if (BUILD_DATA)
    set(UGame_BUILD_SRC ${UGame_Data_SRC} ${UGame_BUILD_SRC})
endif()

if (BUILD_CRYPTO)
    set(UGame_BUILD_SRC ${UGame_Crypto_SRC} ${UGame_BUILD_SRC})
endif()

if (BUILD_NET)
    set(UGame_BUILD_SRC ${UGame_Net_SRC} ${UGame_BUILD_SRC})
endif()

add_library(UGame STATIC ${UGame_BUILD_SRC})
if (BUILD_NET_CLIENT)
    add_library(UGame_NetClient STATIC ${UGame_NetClient_SRC})
endif()

# 代码分组 ########################################################################
if(WIN32)
    source_group("Base" FILES ${UGame_SRC})
    source_group("Policies" FILES ${UGame_Policies_SRC})
    source_group("System" FILES ${UGame_System_SRC})
    source_group("Util" FILES ${UGame_Util_SRC})
    source_group("Binary" FILES ${UGame_Binary_SRC})
    if (BUILD_NET)
        source_group("Net" FILES ${UGame_Net_SRC})
    endif()
    if (BUILD_NET_CLIENT)
        source_group("Net" FILES ${UGame_NetClient_SRC})
    endif()
    if (BUILD_DATA)
        source_group("Data" FILES ${UGame_Data_SRC})
    endif()
    if (BUILD_CRYPTO)
        source_group("Crypto" FILES ${UGame_Crypto_SRC})
    endif()
endif()

# 安装 ############################################################################
if (INSTALL_UGAME)
    install(
        DIRECTORY ${PROJECT_SOURCE_DIR}/
        DESTINATION UGame
        FILES_MATCHING PATTERN "*.h"
        PATTERN "cmake" EXCLUDE
        PATTERN ".*" EXCLUDE
    )
    install(
        TARGETS UGame
        ARCHIVE DESTINATION lib
    )
    if (BUILD_NET_CLIENT)
        install(
            TARGETS UGame_NetClient
            ARCHIVE DESTINATION lib
        )
    endif()
endif()
